using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;


namespace Game.Framework.UI.TableView
{
    public class UITableViewPage : UITableView
    {
        public delegate void DelegateOnPageChanged(int pageIndex);

        private bool _moving;
        private Vector2 _lastContentPos;
        private float _movingCheckDuration;

        /// <summary>
        /// 按页滑动模式，换页回调
        /// </summary>
        private DelegateOnPageChanged _delegatePageChanged = null;

        /// ------------------------------------------
        /// ------------------------------------------
        private float _startDragHorizontal;

        private bool _isDrag = false; //是否拖拽结束  
        private float _startTime;
        public float _smooting = 4; //滑动速度  
        private float _targethorizontal = 0; //滑动的起始坐标  
        private List<float> _posList = new List<float>(); //求出每页的临界角，页索引从0开始  
        public float _dragMaxDeltaOfScreen = 0.3f; //最大滑动距离(超出后按一页)
        private int _currentPageIndex = -1;

        public void SetOnPageChangedDelegate(DelegateOnPageChanged delegatePageChanged)
        {
            _delegatePageChanged = delegatePageChanged;
        }

        private void InitPageView()
        {
            _posList.Clear();
            for (int i = 0; i < _numberOfCells; i++)
            {
                _posList.Add(i * (1f / (_numberOfCells - 1)));
            }
        }

        protected override void OnCreate()
        {
            base.OnCreate();

            _lastContentPos = _scrollRect.content.anchoredPosition;
        }

        public override void ReloadData(ReloadType reloadType = ReloadType.Keep, int startIndex = 0, bool indexAtCenter = true, bool clearCell = false)
        {
            base.ReloadData(reloadType, startIndex, indexAtCenter, clearCell);

            if (NumberOfCells == null) return;

            InitPageView();
        }

        private void FixedUpdate()
        {
            CheckMoving();
        }

        private void Update()
        {
            UpdatePageScroll();
        }


        private void CheckMoving()
        {
            _movingCheckDuration += Time.deltaTime;
            if (_movingCheckDuration <= 0.2f) return;

            _movingCheckDuration = 0f;
            if (_lastContentPos == _scrollRect.content.anchoredPosition)
            {
                if (_moving)
                {
                    _moving = false;
                    _onStopMove?.Invoke();
                }
            }
            else
            {
                _moving = true;
                _lastContentPos = _scrollRect.content.anchoredPosition;
            }
        }

        private void UpdatePageScroll()
        {
            if (!_isDrag && _moving)
            {
                _startTime += 0.05f;
                float t = _startTime * _smooting;
                horizontalNormalizedPosition = Mathf.Lerp(horizontalNormalizedPosition, _targethorizontal, t);
                if (t >= 1)
                    _moving = false;
            }
        }

        protected override void BeginDrag(PointerEventData eventData)
        {
            base.BeginDrag(eventData);

            _moving = true;
            _isDrag = true;
            _startDragHorizontal = horizontalNormalizedPosition;
        }
        
        protected override void EndDrag(PointerEventData eventData)
        {
            base.EndDrag(eventData);

            var delta = horizontalNormalizedPosition - _startDragHorizontal;
            var sign = Mathf.Sign(delta);
            delta = Mathf.Abs(delta);

            delta *= _posList.Count;
            var targetIndex = _currentPageIndex;
            if (delta >= _dragMaxDeltaOfScreen)
            {
                targetIndex += (int)sign;
            }

            GotoPage(targetIndex);
        }

        private void GotoPage(int index)
        {
            if (_currentPageIndex != index)
            {
                _targethorizontal = _posList[index];
                _currentPageIndex = index;
                _isDrag = false;
                _startTime = 0;
                _moving = true;
                _delegatePageChanged?.Invoke(index);
            }
        }
    }
}